﻿using System;

namespace DynamicVm
{
    internal class MemberValue : IMemberValue
    {
        public object GetValue()
        {
            return _value;
        }

        public T GetValue<T>()
        {
            return (T) _value;
        }

        public bool SetValue<T>(T value)
        {
            if (Equals(_value, value)) return false;
            Type valType = SafeGetType(value);

            if (!valType.IsAssignableFrom(_valueType) && 
                !(Equals(value, null) && _valueType.IsClass))
            {
                throw new InvalidCastException();
            }

            _value = value;
            _trigger.OnPropertyChanged(_name);
            return true;
        }

        public MemberValue(ITriggerPropertyChanged trigger, string name, object value)
        {
            Contract.NotNull(trigger, "trigger");
            Contract.NotNull(name, "name");
            _valueType = SafeGetType(value);
            _trigger = trigger;
            _name = name;
            _value = value;
        }

        private static Type SafeGetType(object value)
        {
            return value == null
                       ? typeof (object)
                       : value.GetType();
        }

        private object _value;
        private readonly Type _valueType;
        private readonly string _name;
        private readonly ITriggerPropertyChanged _trigger;
    }
}
